﻿/*-------------------------------------------------------------------------
* 命名空间: SiliconSelect.Common/LogHelper
* 类       名: LogHelper
* 功      能:  LogHelper的类,使用log4net来构建的LogHelper类
* 时      间:  2023/6/20 15:04:16
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using log4net;
using log4net.Appender;
using log4net.Core;
using OfficeOpenXml.Drawing.Controls;
using SiliconSelect.Base;
using SiliconSelect.BLL;
using SiliconSelect.DAL;
using SiliconSelect.DAL.DataEntity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SiliconSelect.Common
{
    public abstract class LogHelper
    {
        // 同一条日志,换行显示的时候左边的填充区域,就是日志显示的时候,内容对齐,日期时间在左边.
        public static int NewLinePaddingVal = 60;

        private static readonly ILog Logger;
        private static readonly ILog LoggerNapons;
        private static readonly ILog LoggerSize;
        private static readonly ILog Logger3D;
        private static readonly ILog LoggerSumdge;
        private static readonly ILog LoggerEdgeBreak;
        private static readonly ILog LoggerSubfissure;

        public static CancellationTokenSource clearLogToken = new CancellationTokenSource();

        // 静态构造函数
        static LogHelper()
        {
            Logger = LogManager.GetLogger(@"MainSLave");
            LoggerNapons = LogManager.GetLogger(@"ResistivityNapons");
            LoggerSize = LogManager.GetLogger(@"Size");
            Logger3D = LogManager.GetLogger(@"ThreeD");
            LoggerSumdge = LogManager.GetLogger(@"Sumdge");
            LoggerEdgeBreak = LogManager.GetLogger(@"EdgeBreak");
            LoggerSubfissure = LogManager.GetLogger(@"Subfissure");
            Task.Run(async () =>
            {
                try
                {
                    while (!clearLogToken.Token.IsCancellationRequested)
                    {
                        DoClearOverDue();
                        WriteLog(LogType.Info, "清除过期日志");
                        await Task.Delay(43200000, clearLogToken.Token);
                    }
                }
                catch (OperationCanceledException)
                {
                    WriteLog(LogType.Info, "清理日志任务已取消");
                }
                catch (Exception ex)
                {
                    WriteLog(LogType.Info, "清理日志任务发生异常: " + ex.Message);
                }
            });
        }

        /// <summary>
        /// 具体的清理过期日志的任务
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        private static void DoClearOverDue()
        {
            int temp = Convert.ToInt32(ConfigurationManager.AppSettings["OverdueDays"]);
            int days = temp == 0 ? 15 : temp;
            DateTime now = DateTime.Now.AddDays(-days);
            IAppender[] array = Logger.Logger.Repository.GetAppenders();
            foreach (var item in array)
            {
                if (!(item is RollingFileAppender roll))
                {
                    continue;
                }
                string? dir = Path.GetDirectoryName(roll.File);
                string[] files = Directory.GetFiles(dir!, "*.log*");
                foreach (string filePath in files)
                {
                    FileInfo file = new FileInfo(filePath);
                    if (file.CreationTime < now || file.LastWriteTime < now)
                    {
                        try
                        {
                            file.Delete();
                        }
                        catch (Exception ex)
                        {
                            WriteLog(LogType.Info, "日志清理失败: " + ex.Message);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 电阻率日志写入函数
        /// </summary>
        /// <param name="type"></param>
        /// <param name="message"></param>
        /// <param name="errorCode"></param>
        public static void WriteLogNapons(LogType type, string? message, string errorCode = "P00")
        {
            AlarmRecordEntity? alarm = new AlarmRecordEntity();
            if (errorCode != "P00")
            {
                List<string> alarmInfo = GetAlarmInfoByErrorCodeNapons(errorCode);
            }

            switch (type)
            {
                case LogType.Info:
                    LoggerNapons.Info(message);
                    break;
                case LogType.Debug:
                    LoggerNapons.Debug(message);
                    break;
                case LogType.Warn:
                    LoggerNapons.Warn(message);
                    break;
                case LogType.Exception:
                    LoggerNapons.Error(message);
                    break;
                case LogType.Fatal:
                    LoggerNapons.Fatal(message);
                    break;
                case LogType.TestShow:
                    LoggerNapons.Debug(message);
                    break;
            }
        }

        public static void WriteLogSize(LogType type, string? message, string errorCode = "P00")
        {
            //AlarmRecordEntity? alarm = new AlarmRecordEntity();
            //if (errorCode != "P00")
            //{
            //    alarm.AlarmCode = errorCode;
            //    alarm.Content = message;
            //    var alarmInfo = GetAlarmInfoByErrorCodeSize(errorCode);
            //    if (alarmInfo != null)
            //    {
            //        alarm.Content = alarmInfo[0];
            //        alarm.SolutionHelp = alarmInfo[1];
            //    }

            //    if (alarm != null)
            //    {
            //        LocalDataAccess.InsertAlarmRecord(alarm);
            //    }
            //}
            switch (type)
            {
                case LogType.Info:
                    LoggerSize.Info(message);
                    break;
                case LogType.Debug:
                    LoggerSize.Debug(message);
                    break;
                case LogType.Warn:
                    LoggerSize.Warn(message);
                    break;
                case LogType.Exception:
                    LoggerSize.Error(message);
                    break;
                case LogType.Fatal:
                    LoggerSize.Fatal(message);
                    break;
                case LogType.TestShow:
                    LoggerSize.Debug(message);
                    break;
            }
        }

        public static void WriteLog3D(LogType type, string? message, string errorCode = "P00")
        {
            //AlarmRecordEntity? alarm = new AlarmRecordEntity();
            //if (errorCode != "P00")
            //{
            //    alarm.AlarmCode = errorCode;
            //    alarm.Content = message;
            //    List<string> alarmInfo = GetAlarmInfoByErrorCode3D(errorCode);
            //    if (alarmInfo != null)
            //    {
            //        alarm.Content = alarmInfo[0];
            //        alarm.SolutionHelp = alarmInfo[1];
            //    }

            //    if (alarm != null)
            //    {
            //        LocalDataAccess.InsertAlarmRecord(alarm);
            //    }
            //}
            switch (type)
            {
                case LogType.Info:
                    Logger3D.Info(message);
                    break;
                case LogType.Debug:
                    Logger3D.Debug(message);
                    break;
                case LogType.Warn:
                    Logger3D.Warn(message);
                    break;
                case LogType.Exception:
                    Logger3D.Error(message);
                    break;
                case LogType.Fatal:
                    Logger3D.Fatal(message);
                    break;
                case LogType.TestShow:
                    Logger3D.Debug(message);
                    break;
            }
        }

        public static void WriteLogSumdge(LogType type, string? message, string errorCode = "P00")
        {
            //AlarmRecordEntity? alarm = new AlarmRecordEntity();
            //if (errorCode != "P00")
            //{
            //    alarm.AlarmCode = errorCode;
            //    alarm.Content = message;
            //    List<string> alarmInfo = GetAlarmInfoByErrorCodeSumdge(errorCode);
            //    if (alarmInfo != null)
            //    {
            //        alarm.Content = alarmInfo[0];
            //        alarm.SolutionHelp = alarmInfo[1];
            //    }

            //    if (alarm != null)
            //    {
            //        LocalDataAccess.InsertAlarmRecord(alarm);
            //    }
            //}
            switch (type)
            {
                case LogType.Info:
                    LoggerSumdge.Info(message);
                    break;
                case LogType.Debug:
                    LoggerSumdge.Debug(message);
                    break;
                case LogType.Warn:
                    LoggerSumdge.Warn(message);
                    break;
                case LogType.Exception:
                    LoggerSumdge.Error(message);
                    break;
                case LogType.Fatal:
                    LoggerSumdge.Fatal(message);
                    break;
                case LogType.TestShow:
                    LoggerSumdge.Debug(message);
                    break;
            }
        }

        public static void WriteLogEdgeBreak(LogType type, string? message, string errorCode = "P00")
        {
            //AlarmRecordEntity? alarm = new AlarmRecordEntity();
            //if (errorCode != "P00")
            //{
            //    alarm.AlarmCode = errorCode;
            //    alarm.Content = message;
            //    List<string> alarmInfo = GetAlarmInfoByErrorCodeEdgeBreak(errorCode);
            //    if (alarmInfo != null)
            //    {
            //        alarm.Content = alarmInfo[0];
            //        alarm.SolutionHelp = alarmInfo[1];
            //    }

            //    if (alarm != null)
            //    {
            //        LocalDataAccess.InsertAlarmRecord(alarm);
            //    }
            //}
            switch (type)
            {
                case LogType.Info:
                    LoggerEdgeBreak.Info(message);
                    break;
                case LogType.Debug:
                    LoggerEdgeBreak.Debug(message);
                    break;
                case LogType.Warn:
                    LoggerEdgeBreak.Warn(message);
                    break;
                case LogType.Exception:
                    LoggerEdgeBreak.Error(message);
                    break;
                case LogType.Fatal:
                    LoggerEdgeBreak.Fatal(message);
                    break;
                case LogType.TestShow:
                    LoggerEdgeBreak.Debug(message);
                    break;
            }
        }

        public static void WriteLogSubfissure(LogType type, string? message, string errorCode = "P00")
        {
            //AlarmRecordEntity? alarm = new AlarmRecordEntity();
            //if (errorCode != "P00")
            //{
            //    alarm.AlarmCode = errorCode;
            //    alarm.Content = message;
            //    List<string> alarmInfo = GetAlarmInfoByErrorCodeSubfissure(errorCode);
            //    if (alarmInfo != null)
            //    {
            //        alarm.Content = alarmInfo[0];
            //        alarm.SolutionHelp = alarmInfo[1];
            //    }

            //    if (alarm != null)
            //    {
            //        LocalDataAccess.InsertAlarmRecord(alarm);
            //    }
            //}
            switch (type)
            {
                case LogType.Info:
                    LoggerSubfissure.Info(message);
                    break;
                case LogType.Debug:
                    LoggerSubfissure.Debug(message);
                    break;
                case LogType.Warn:
                    LoggerSubfissure.Warn(message);
                    break;
                case LogType.Exception:
                    LoggerSubfissure.Error(message);
                    break;
                case LogType.Fatal:
                    LoggerSubfissure.Fatal(message);
                    break;
                case LogType.TestShow:
                    LoggerSubfissure.Debug(message);
                    break;
            }
        }

        private static List<string> GetAlarmInfoByErrorCodeSubfissure(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCodeEdgeBreak(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCodeSumdge(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCode3D(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCodeSize(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCodeNapons(string errorCode)
        {
            return null!;
        }

        private static List<string> GetAlarmInfoByErrorCodeMain(string errorCode)
        {
            List<string> alarmInfo = new List<string>();
            try
            {
                return alarmInfo;
            }
            catch (Exception)
            {
                alarmInfo.Add($"获取报警代码{errorCode} 出现异常");
                alarmInfo.Add($"获取报警代码{errorCode} 出现异常");
                return alarmInfo;
            }
        }

        public static void WriteLogSlave(LogType type, string? message, string? clientName)
        {
            if (clientName!.Equals("尺寸"))
            {
                WriteLogSize(type, message);
            }
            else if (clientName!.Equals("3D"))
            {
                WriteLog3D(type, message);
            }
            else if (clientName!.Equals("崩边隐裂") && message!.Contains("Subfi"))
            {
                WriteLogSubfissure(type, message);
            }
            else if (clientName!.Equals("脏污"))
            {
                WriteLogSumdge(type, message);
            }
            else if (clientName!.Equals("电阻率"))
            {
                WriteLogNapons(type, message);
            }
            else if (clientName!.Equals("国产电阻率"))
            {
                WriteLog(type, message);
            }
            else
            {
                WriteLogEdgeBreak(type, message);
            }
        }



        /// <summary>
        /// 日志写入,有的日志不一定要从数据库去获取.
        /// </summary>
        /// <param name="type">日志的种类</param>
        /// <param name="message">具体的日志信息</param>
        public static void WriteLog(LogType type, string? message, string errorCode = "P00", bool isInsert = false)
        {
            if (errorCode != "P00")
            {
                DataResult<AlarmRecordEntity> alarmRes = GetAlarmByCodeFromSql(errorCode);

                if (alarmRes.State && alarmRes.Data != null)
                {
                    if (!string.IsNullOrEmpty(message))
                    {
                        alarmRes.Data!.Content = message;
                    }
                    else
                    {
                        message = alarmRes.Data!.Content;
                    }
                    LocalDataAccess.InsertAlarmRecord(alarmRes.Data!, isInsert);
                    LocalDataAccess.InsertAlarmMainShow(alarmRes.Data!, isInsert);
                }
                else
                {
                    WriteLog(LogType.Fatal, $"Code = {errorCode} 的报警信息不存在,在报警设置表里请添加 {errorCode} 类型的报警信息");
                }
                if (!isInsert)
                {
                    return; // 如果不是插入的报警就直接返回.不然日志会一直显示.
                }
            }
            switch (type)
            {
                case LogType.Info:
                    Logger.Info(message);
                    break;
                case LogType.Debug:
                    Logger.Debug(message);
                    break;
                case LogType.Warn:
                    Logger.Warn(message);
                    break;
                case LogType.Exception:
                    Logger.Error(message);
                    break;
                case LogType.Fatal:
                    Logger.Fatal(message);
                    break;
                case LogType.TestShow:
                    Logger.Debug(message);
                    break;
            }
        }

        private static DataResult<AlarmRecordEntity> GetAlarmByCodeFromSql(string errorCode)
        {
            string tableName = TableNames.AlarmSettingTb;
            DataResult<AlarmRecordEntity> alarmResult = new DataResult<AlarmRecordEntity>();
            AlarmRecordEntity alarmRecord = new AlarmRecordEntity();
            try
            {
                string sqlQuery = $"Select * from {tableName} where [AlarmCode] = @AlarmCode Order By Id Desc";
                SqlParameter[] queryParameters = new SqlParameter[]
                {
                        new SqlParameter($"@AlarmCode",errorCode),
                };
                DataTable table = DataAccess.GetDataTables(sqlQuery, queryParameters);
                if (table.Rows.Count > 0)
                {
                    alarmRecord.AlarmCode = errorCode;
                    alarmRecord.Content = table.Rows[0].Field<string>("Content");
                    alarmRecord.SolutionHelp = table.Rows[0].Field<string>("SolutionHelp");
                    alarmResult.Data = alarmRecord;
                    alarmResult.State = true;
                }
            }
            catch (Exception ex)
            {
                alarmResult.Message = ExceptionHelper.GetFullException(ex, MethodBase.GetCurrentMethod()!);
            }
            return alarmResult;
        }
    }


    public enum LogType
    {
        Info,
        Debug,
        Warn,
        Exception,
        Fatal,
        TestShow, // 用来测试流程的时候显示,方便查看
    }
}
